package com.koc.robot;

import android.content.Context;
import android.opengl.GLES11;

import com.koc.robot.common.Vector;
import com.koc.robot.common.Vector3;

public class Player {
	private Context mContext;
	private Texture mTexture;
	private Quad mQuad[] = new Quad[2];	
	
	private Scene mScene;
	private BlockPoint mPosition;
	private float mScale = 1.0f;
	private Vector3 mShowPos = new Vector3();
	
	private static final int PLAYER_SIZE = 20;
	
	private static final int MOVE_POS_X = 0;
	private static final int MOVE_NEG_X = 1;
	private static final int MOVE_POS_Z = 2;
	private static final int MOVE_NEG_Z = 3;
	
	public Player(Context context, Scene scene)
	{
		mContext = context;	
		
		mPosition = new BlockPoint();
		mScene = scene;
	}
	
	public void init()
	{
		mTexture = new Texture(mContext);
		//mTexture.load(R.drawable.robot);
		mTexture.load("player.png");
		mQuad[0] = new Quad(mTexture, 0, 0, 
				PLAYER_SIZE, PLAYER_SIZE);
		mQuad[1] = new Quad(mTexture, PLAYER_SIZE, 0, 
				PLAYER_SIZE, PLAYER_SIZE);
	}
	
	public void initPosition(BlockPoint p)
	{
		mShowPos.x = mPosition.x = p.x;
		mShowPos.y = mPosition.y = p.y;
		mShowPos.z = mPosition.z = p.z;		
	}
	
	public BlockPoint getPositin()
	{
		return mPosition;
	}
	
	public void render(float depth)
	{	
		Vector pos = mScene.convertGRDToSCR(mShowPos.x, mShowPos.y, mShowPos.z);
		
		GLES11.glMatrixMode(GLES11.GL_MODELVIEW_MATRIX);
		GLES11.glPushMatrix();
		
		pos.y = pos.y + mScene.getBlockWidth() / 2 * mScene.getPitch() * 0.6f;
		GLES11.glTranslatef(pos.x, pos.y, depth);		
		GLES11.glScalef(mScale, mScale, 1.0f);
		GLES11.glTranslatef(-PLAYER_SIZE / 2, -PLAYER_SIZE, 0.0f);
		
		mQuad[0].render(0, 0, PLAYER_SIZE, PLAYER_SIZE);
		
		GLES11.glPopMatrix();
	}
	
	public void update(float dt)
	{
		mShowPos.x = smoothMove(mShowPos.x, mPosition.x, dt);
		mShowPos.y = mPosition.y;
		mShowPos.z = smoothMove(mShowPos.z, mPosition.z, dt);
	}
	
	private float smoothMove(float start, float target, float dt)
	{
		float ret = start;
		if(start < target)
		{
			ret = start + 3 * dt + (target - start) / 3.0f * dt * 20;
			if(ret > target)
				ret = target;
		}
		else if(start > target)
		{
			ret = start - 3 * dt - (start - target) / 3.0f * dt * 20;
			if(ret < target)
				ret = target;
		}
		
		return ret;
	}
	
	public void setScale(float s)
	{
		mScale = s;
	}
	
	public float getScale()
	{
		return mScale;
	}
	
	public Texture getTexture()
	{
		return mTexture;
	}
	
	public void onButtonClicked(int buttonId)
	{
		float rotation = mScene.getRotation();
		float pitch = mScene.getPitch();
		int map2D[][] = mScene.getMap2D();
		Map map = mScene.getMap();
		int mapWidth = map.getMapWidth();
		int mapHeight = map.getMapHeight();
		int mapDepth = map.getMapDepth();
		
		if(rotation == Common.PI_025 && pitch == 0.0f)	//back
		{
			switch(buttonId)
			{
			case R.id.button_right:
				if(mPosition.x > 0 &&
					(map2D[mapWidth - mPosition.x - 1 + 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mapWidth - mPosition.x - 1 + 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.x = mPosition.x - 1;
				break;
			case R.id.button_left:
				if(mPosition.x < mapWidth - 1 &&
					(map2D[mapWidth - mPosition.x - 1 - 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mapWidth - mPosition.x - 1 - 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.x = mPosition.x + 1;
				break;
			}
		}
		else if(rotation == Common.PI_075 && pitch == 0.0f) //left
		{
			switch(buttonId)
			{
			case R.id.button_right:
				if(mPosition.z > 0 &&
					(map2D[mapDepth - mPosition.z - 1 - 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mapDepth - mPosition.z - 1 - 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.z = mPosition.z - 1;
				break;
			case R.id.button_left:
				if(mPosition.z < mapDepth - 1 &&
					(map2D[mapDepth - mPosition.z - 1 + 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mapDepth - mPosition.z - 1 + 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.z = mPosition.z + 1;
				break;
			}
		}
		else if(rotation == Common.PI_125 && pitch == 0.0f)
		{
			switch(buttonId)
			{
			case R.id.button_left:
				if(mPosition.x > 0 &&
					(map2D[mPosition.x - 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mPosition.x - 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.x = mPosition.x - 1;
				break;
			case R.id.button_right:
				if(mPosition.x < mapWidth - 1 &&
					(map2D[mPosition.x + 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mPosition.x + 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.x = mPosition.x + 1;
				break;
			}
		}
		else if(rotation == Common.PI_175 && pitch == 0.0f)
		{
			switch(buttonId)
			{
			case R.id.button_left:
				if(mPosition.z > 0 &&
					(map2D[mPosition.z - 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mPosition.z - 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.z = mPosition.z - 1;
				break;
			case R.id.button_right:
				if(mPosition.z < mapDepth - 1 &&
					(map2D[mPosition.z + 1][mPosition.y] != Block.INVALID_TILENUM) &&
					(mPosition.y == mapHeight - 1 || map2D[mPosition.z + 1][mPosition.y + 1] == Block.INVALID_TILENUM))
					mPosition.z = mPosition.z + 1;
				break;
			}
		}
		else
		{
			int moveDir = 0;
			if(rotation >= Common.PI_125 && rotation < Common.PI_175)
			{
				switch(buttonId)
				{
				case R.id.button_left:
					moveDir = MOVE_NEG_X;
					break;
				case R.id.button_right:
					moveDir = MOVE_POS_X;
					break;
				case R.id.button_up:
					moveDir = MOVE_POS_Z;
					break;
				case R.id.button_down:
					moveDir = MOVE_NEG_Z;
					break;
				}
			}
			else if(rotation >= Common.PI_175 || rotation < Common.PI_025)
			{
				switch(buttonId)
				{
				case R.id.button_left:
					moveDir = MOVE_NEG_Z;
					break;
				case R.id.button_right:
					moveDir = MOVE_POS_Z;
					break;
				case R.id.button_up:
					moveDir = MOVE_NEG_X;
					break;
				case R.id.button_down:
					moveDir = MOVE_POS_X;
					break;
				}
			}
			else if(rotation >= Common.PI_025 && rotation < Common.PI_075)
			{
				switch(buttonId)
				{
				case R.id.button_left:
					moveDir = MOVE_POS_X;
					break;
				case R.id.button_right:
					moveDir = MOVE_NEG_X;
					break;
				case R.id.button_up:
					moveDir = MOVE_NEG_Z;
					break;
				case R.id.button_down:
					moveDir = MOVE_POS_Z;
					break;
				}
			}
			else // rotation >= Common.PI_075 && rotation < Common.PI_125
			{
				switch(buttonId)
				{
				case R.id.button_left:
					moveDir = MOVE_POS_Z;
					break;
				case R.id.button_right:
					moveDir = MOVE_NEG_Z;
					break;
				case R.id.button_up:
					moveDir = MOVE_POS_X;
					break;
				case R.id.button_down:
					moveDir = MOVE_NEG_X;
					break;
				}
			}
			
			if(pitch == 1.0f)
			{
				boolean moved = false;
				switch(moveDir)
				{
				case MOVE_POS_X:
					if(mPosition.x < mapWidth - 1 &&
							map2D[mPosition.x + 1][mPosition.z] != Block.INVALID_TILENUM &&
							map2D[mPosition.x + 1][mPosition.z] != 2)
					{
						mPosition.x = mPosition.x + 1;
						moved = true;
					}
					break;
				case MOVE_NEG_X:
					if(mPosition.x > 0 &&
							map2D[mPosition.x - 1][mPosition.z] != Block.INVALID_TILENUM &&
							map2D[mPosition.x - 1][mPosition.z] != 2)
					{
						mPosition.x = mPosition.x - 1;
						moved = true;
					}
					break;
				case MOVE_POS_Z:
					if(mPosition.z < mapDepth - 1 &&
							map2D[mPosition.x][mPosition.z + 1] != Block.INVALID_TILENUM &&
							map2D[mPosition.x][mPosition.z + 1] != 2)
					{
						mPosition.z = mPosition.z + 1;
						moved = true;
					}
					break;
				case MOVE_NEG_Z:
					if(mPosition.z > 0 &&
							map2D[mPosition.x][mPosition.z - 1] != Block.INVALID_TILENUM &&
							map2D[mPosition.x][mPosition.z - 1] != 2)
					{
						mPosition.z = mPosition.z - 1;
						moved = true;
					}
					break;
				}
				
				if(moved == true)
				{
					mPosition.y = mapHeight - 1;
					while(map.isValidBlock(mPosition.x, mPosition.y, mPosition.z))
					{
						mPosition.y = mPosition.y - 1;
					}
				}
			}
			else
			{
				switch(moveDir)
				{
				case MOVE_POS_X:
					if(mPosition.x < map.getMapWidth() - 1 &&
						map.isValidBlock(mPosition.x + 1, mPosition.y, mPosition.z) &&
						(mPosition.y == map.getMapHeight() - 1 || !map.isValidBlock(mPosition.x + 1, mPosition.y +1, mPosition.z)))
					{
						mPosition.x += 1;
					}
					break;
				case MOVE_NEG_X:
					if(mPosition.x > 0 &&
						map.isValidBlock(mPosition.x - 1, mPosition.y, mPosition.z) &&
						(mPosition.y == map.getMapHeight() - 1 || !map.isValidBlock(mPosition.x - 1, mPosition.y +1, mPosition.z)))
						{
							mPosition.x -= 1;
						}
					break;
				case MOVE_POS_Z:
					if(mPosition.z < map.getMapDepth() - 1 &&
						map.isValidBlock(mPosition.x, mPosition.y, mPosition.z + 1) &&
						(mPosition.y == map.getMapHeight() - 1 || !map.isValidBlock(mPosition.x, mPosition.y +1, mPosition.z + 1)))
						{
							mPosition.z += 1;
						}
					break;
				case MOVE_NEG_Z:
					if(mPosition.z > 0 &&
						map.isValidBlock(mPosition.x, mPosition.y, mPosition.z - 1) &&
						(mPosition.y == map.getMapHeight() - 1 || !map.isValidBlock(mPosition.x, mPosition.y +1, mPosition.z - 1)))
						{
							mPosition.z -= 1;
						}
					break;
				}	
			}
		}
	}
	
	private void playerMoveInfront()
	{
		
	}
	
	//whether is drawing in block
	public boolean isInBlock(int x, int y, int z, boolean ceilX, boolean ceilY, boolean ceilZ)
	{
		return (x == (ceilX ? Math.ceil(mShowPos.x) : Math.floor(mShowPos.x)) &&
				y == (ceilY ? Math.ceil(mShowPos.y) : Math.floor(mShowPos.y)) &&
				z == (ceilZ ? Math.ceil(mShowPos.z) : Math.floor(mShowPos.z)));
	}
}
